<?php
class DigSearch_Service_Index
{
    const SEARCH_INDEX_KEY = 'search_indexes';
    const SEARCH_INDEX_MAPPING_KEY = 'search_index_item_mapping';
    public static function listIndexes() {
        if(Dig_Service_Core::hasParam(self::SEARCH_INDEX_KEY)) {
            return Dig_Service_Core::getParam(self::SEARCH_INDEX_KEY);
        }
        $searchIndexes = Dig_Service_Module::settings(null, 'searchIndex');
        if($searchIndexes) {
            $indexArray = array();
            foreach ($searchIndexes as $module => $indexes) {
                if(count($indexes) == 1) {$indexes = array($indexes);}
                foreach ($indexes as $index) {
                    foreach ($index as $key => $category) {
                        foreach ($category as $config) {
                            $indexArray[$key][] = $config;
                        }
                    }
                }
                
            }
            Dig_Service_Core::setParam(self::SEARCH_INDEX_KEY, $indexArray);
            return $indexArray;
        }
    }

    public function getIndexCategories($index) {
        $indexes = self::listIndexes();
        if(!isset($indexes[$index])) {
            return false;
        }
        $categories = array();
        foreach($indexes[$index] as $indexConfig) {
            if(array_search($indexConfig['category'], $categories) ===  false) {
                $categories[] = $indexConfig['category'];
            }
        }
        if(count($categories) > 0) {
            return $categories;
        }
    }

    public static function getIndexConfig($index) {
        $indexes = self::listIndexes();
        if(isset($indexes[$index])) {
            return $indexes[$index];
        }
    }

    public static function getItemMap($index, $namespace) {
        if(Dig_Service_Core::hasParam(self::SEARCH_INDEX_MAPPING_KEY)) {
            $map = Dig_Service_Core::getParam(self::SEARCH_INDEX_MAPPING_KEY);
        } else {
            $indexConfig = self::getIndexConfig($index);
            if($indexConfig) {
                $map = array();
                foreach ($indexConfig as $config) {
                    $map[ $config['filter'] ] = $config['mapping'];
                }
                Dig_Service_Core::setParam(self::SEARCH_INDEX_MAPPING_KEY, $map);
            }
        }
        return $map[$namespace];
    }

    public static function getIndex($key = 'default') {
        $pathToIndex = self::indexPath($key);
        return Zend_Search_Lucene::open($pathToIndex);
    }

    public static function addItem($index, $id,$category,$content) {
        $doc = new Zend_Search_Lucene_Document();
        $doc->addField(Zend_Search_Lucene_Field::UnIndexed('guid', $id));
        $doc->addField(Zend_Search_Lucene_Field::Text('category', $category));
        $doc->addField(Zend_Search_Lucene_Field::Unstored('content', $content));
        // suppress notices
        @$index->addDocument($doc);
    }

    public static function buildIndex($key = 'default') {
        $indexConfig = self::getIndexConfig($key);
        //Zend_Debug::dump($indexConfig);
        if(! $indexConfig) {
            return false;
        }
        $index = Zend_Search_Lucene::create(self::indexPath($key));
        foreach ($indexConfig as $category) {
            $rootItem = DigCms_Service_Item::getItemByPath($category['path'], false); // the search engine only indexes items in the site root
            if($rootItem) {
                //Zend_Debug::dump($category['path'], $rootItem->name);
                $items = $rootItem->descendents($category['filter'], null, true);
                foreach ($items as $item) {
                    if(is_array($category['mapping']['content'])) {
                        $content = null;
                        foreach ($category['mapping']['content'] as $contentField) {
                            $content .= $item->$contentField;
                        }
                    } else {
                        $contentKey = $category['mapping']['content'];
                        $content = $item->$contentKey;
                    }
                    self::addItem($index, $item->id, $category['category'], $content);
                }
            }
        }
        $index->optimize();
        if(self::exists($key)) {
            return true;
        }
    }

    public static function exists($index) {
        $pathToIndex = self::indexPath($index);
        if(Zend_Search_Lucene::open($pathToIndex)) {
            return true;
        }
    }

    public static function indexPath($index) {
        return APPLICATION_PATH . '/data/lucene/' . $index;
    }

    public static function keywordSearch($query, $category = null, $key = 'default') {
        $index = self::getIndex($key);
        if(!$index) {
            throw new DigSearch_Exception('The system encountered an error searching for ' . $keywords);
        }
        if($category != null) {
            $query .= ' AND category:"' . $category . '"';
        }
        $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($query);
        $result = $index->find($userQuery);
        if($result) {
            $resultArray = array();
            foreach($result as $hit) {
                $item = DigCms_Model_Item::factory($hit->guid);
                if($item) {
                    if(!empty($item->namespace)) {
                        $map = self::getItemMap($key, $item->namespace);
                    } else {
                        $map = array('headline' => 'headline', 'intro' => 'intro');
                    }
                    
                    $resultArray[] = array(
                        'item'  => $item,
                        'headline'  => $item->$map['headline'],
                        'url'       => DigNavigation_Service_Menu::getUrlForItem($item),
                        'intro'     => $item->$map['intro']
                    );
                }
            }
            return $resultArray;
        }
    }
}
?>
